package com.javastudy.jdkfeature.jdk5.generics;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by admin on 2017/5/2.
 */
public class TestGerner {
    //定义一个打印信息方法
    public static void printPersonInfoA(List<Person> persons){
        for(Person person:persons){
            System.out.println(person);
        }
    }

    //使用通配符方法
    public static void printPersonInfoB(List<? extends Person> persons){
        for(Person person:persons){
            System.out.println(person);
        }
    }


    /**
     * 结果是
     * Person [name=AA, age=12]
     * Person [name=BB, age=34]
     * Person [name=CC, age=56]
     * Student [school=TInghua]
     */

    //任意通配符方法
    //取出来的时候，只能是Object类
    public static void printPersonInfoC(List<?> persons){
        for(Object person:persons){
            System.out.println(person);
        }
    }

    //通配符的安全性问题
    //但是，将多种类型加入到同一个泛型集合中中不是类型安全的
    // add 方法有类型参数 E 作为集合的元素类型。我们传给 add 的任何参数都必须是一个未知类型的子类。因为我们不知道那是什么类型，所以我们无法传任何东西进去。
    // 唯一的例外是 null，它是所有类型的成员。
    public static void printPersonInfoD(List<? extends Person> persons){
        //加入null是可行的
        persons.add(null);
        //这句话编译出错，因为不能确定Person中到底是什么类型（可能是Person类型，也可能是其子类型）
        //--------------所以往里面添加任何类型元素都是不行的
       // persons.add(new Person("DD",78));

        //向外取数据是合法的
        //我们可以调用 get()方法并使用其返回值。返回值是一个未知的类型，但是我们知道，这里它总是一个Person
        for(Person person:persons){
            System.out.println(person);
        }
    }


    public static void main(String[] args) {

        List<Person> persons = new ArrayList<>();
        persons.add(new Person("AA",12));
        persons.add(new Person("BB",34));
        persons.add(new Person("CC",56));
        //这里调用是没有问题的
        printPersonInfoA(persons);
        printPersonInfoB(persons);

        List<Student> stus = new ArrayList<>();
        stus.add(new Student("TT",22,"TInghua"));

        //这里调用是不对的
        //因为Student是Person的子类，但是List<Student>却不是List<Person>的子类
        //printPersonInfoA(stus);
        printPersonInfoB(stus); //这里是没问题的
    }
}
